Completed
Push — master ( 2b4a65...dae5f9 )
by Sander
39s
created

$j.ready   B

Complexity

Conditions 5
Paths 12

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
c 0
b 0
f 0
nc 12
nop 1
dl 0
loc 15
rs 8.8571
1
/* global API */
2
var $j = jQuery.noConflict();
3
4
$j(document).ready(function () {
5
    var _this = this;
6
    Array.prototype.findUrl = function (match) {
0 ignored issues
show
Compatibility Best Practice introduced by
You are extending the built-in type Array. This may have unintended consequences on other objects using this built-in type. Consider subclassing instead.
Loading history...
7
        return this.filter(function (item) {
8
            return typeof item === 'string' && item.indexOf(match) > -1;
9
        });
10
    };
11
12
    function removePasswordPicker() {
13
        $j('.passwordPickerIframe').remove();
14
    }
15
16
    _this.removePasswordPicker = removePasswordPicker;
17
18
    function enterLoginDetails(login) {
19
        var username;
20
21
        if (login.hasOwnProperty('username')) {
22
            username = (login.username !== '' ) ? login.username : login.email;
23
        }
24
        if(!username){
25
            username = null;
26
        }
27
28
        fillPassword(username, login.password);
29
        if ($j('.passwordPickerIframe').is(':visible')) {
30
            removePasswordPicker();
31
        }
32
    }
33
34
    _this.enterLoginDetails = enterLoginDetails;
35
36
37
    function showPasswordPicker(form) {
38
        if ($j('.passwordPickerIframe').length > 1) {
39
            return;
40
        }
41
        var loginField = $j(form[0]);
42
        var loginFieldPos = loginField.offset();
43
        var position = $j(form[1]).position();
0 ignored issues
show
Unused Code introduced by
The assignment to variable position seems to be never used. Consider removing it.
Loading history...
44
        var passwordField = $j(form[1]);
45
        var passwordFieldPos = passwordField.offset();
46
47
        var left = (loginFieldPos) ? loginFieldPos.left : passwordFieldPos.left;
48
        var top = (loginFieldPos) ? loginFieldPos.top : passwordFieldPos.top;
49
        var maxZ = Math.max.apply(null,
50
            $j.map($j('body *'), function (e) {
51
                if ($j(e).css('position') !== 'static')
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if $j(e).css("position") !== "static" is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
52
                    return parseInt($j(e).css('z-index')) || 1;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
53
            }));
54
        if (loginFieldPos && passwordFieldPos.top > loginFieldPos.top) {
55
            //console.log('login fields below each other')
56
            top = passwordFieldPos.top + passwordField.height() + 10;
57
        } else {
58
            // console.log('login fields next to each other')
59
            if(loginFieldPos){
60
                top =  top + loginField.height() + 10;
61
            } else {
62
                top =  top + passwordField.height() + 10;
63
            }
64
        }
65
66
67
        var pickerUrl = API.extension.getURL('/html/inject/password_picker.html');
68
69
        var picker = $j('<iframe class="passwordPickerIframe" scrolling="no" height="385" width="350" frameborder="0" src="' + pickerUrl + '"></iframe>');
70
        picker.css('position', 'absolute');
71
        picker.css('left', left);
72
        picker.css('z-index', maxZ + 10);
73
        picker.css('top', top);
74
        $j('body').prepend($j(picker));
75
        // picker.css('width', $j(form).width());
76
        $j('.passwordPickerIframe:not(:last)').remove();
77
    }
78
79
    function createFormIcon(el, form) {
80
        var offset = el.offset();
0 ignored issues
show
Unused Code introduced by
The assignment to variable offset seems to be never used. Consider removing it.
Loading history...
81
        var width = el.width();
82
        var height = el.height() * 1;
83
        var margin = (el.css('margin')) ? parseInt(el.css('margin').replace('px', '')) : 0;
0 ignored issues
show
Unused Code introduced by
The variable margin seems to be never used. Consider removing it.
Loading history...
84
        var padding = (el.css('padding')) ? parseInt(el.css('padding').replace('px', '')) : 0;
0 ignored issues
show
Unused Code introduced by
The variable padding seems to be never used. Consider removing it.
Loading history...
85
86
        var pickerIcon = API.extension.getURL('/icons/icon.svg');
87
        $j(el).css('background-image', 'url("' + pickerIcon + '")');
88
        $j(el).css('background-repeat', 'no-repeat');
89
        //$j(el).css('background-position', '');
90
        $j(el).css('cssText', el.attr('style')+' background-position: right 3px center !important;');
91
92
93
        function onClick(e) {
94
            e.preventDefault();
95
            var offsetX = e.offsetX;
96
            var offsetRight = (width - offsetX);
97
            if (offsetRight < height) {
98
                showPasswordPicker(form);
99
            }
100
        }
101
102
        // $j(el).bind('click', onClick);
103
        $j(el).click(onClick);
104
105
    }
106
107
    function createPasswordPicker(form) {
108
        for (var i = 0; i < form.length; i++) {
109
            var el = $j(form[i]);
110
            createFormIcon(el, form);
111
112
        }
113
    }
114
115
    function formSubmitted(fields) {
116
        var user = fields[0].value;
117
        var pass = fields[1].value;
118
        var params = {
119
            username: user,
120
            password: pass
121
        };
122
        //Disable password mining
123
        //$j(fields[1]).attr('type', 'hidden');
124
        API.runtime.sendMessage(API.runtime.id, {method: "minedForm", args: params});
125
126
    }
127
128
    function inIframe() {
129
        try {
130
            return window.self !== window.top;
131
        } catch (e) {
132
            return true;
133
        }
134
    }
135
136
    function showDoorhanger(data) {
137
        if (inIframe()) {
138
            return;
139
        }
140
        data.data.currentLocation = window.location.href;
141
        API.runtime.sendMessage(API.runtime.id, {method: "setDoorhangerData", args: data});
142
        var pickerUrl = API.extension.getURL('/html/inject/doorhanger.html');
143
144
        var doorhanger = $j('<iframe id="password-toolbarIframe" style="display: none;" scrolling="no" height="80" width="100%" frameborder="0" src="' + pickerUrl + '"></iframe>');
145
        $j('#password-toolbarIframe').remove();
146
        $j('body').prepend(doorhanger);
147
        $j('#password-toolbarIframe').fadeIn();
148
    }
149
150
    _this.showDoorhanger = showDoorhanger;
151
152
    function showUrlUpdateDoorhanger(data) {
153
        var buttons = ['cancel', 'updateUrl'];
154
        showDoorhanger({
155
            data: data.data,
156
            buttons: buttons
157
        });
158
    }
159
160
    _this.showUrlUpdateDoorhanger = showUrlUpdateDoorhanger;
161
162
    function checkForMined() {
163
        if (inIframe()) {
164
            return;
165
        }
166
167
        API.runtime.sendMessage(API.runtime.id, {method: "getMinedData"}).then(function (data) {
168
            if (!data) {
169
                return;
170
            }
171
            if (data.hasOwnProperty('username') && data.hasOwnProperty('password') && data.hasOwnProperty('url')) {
172
                var buttons = ['cancel', 'save', 'ignore'];
173
                showDoorhanger({data: data, buttons: buttons});
174
            }
175
        });
176
    }
177
178
179
    function closeDoorhanger() {
180
        $j('#password-toolbarIframe').slideUp(400, function () {
181
            $j('#password-toolbarIframe').remove();
182
        });
183
    }
184
185
    _this.closeDoorhanger = closeDoorhanger;
186
187
    function initForms() {
188
        API.runtime.sendMessage(API.runtime.id, {method: 'getRuntimeSettings'}).then(function (settings) {
189
            var disablePasswordPicker = settings.disablePasswordPicker;
190
            var url = window.location.href;
191
            var loginFields = getLoginFields();
192
            if (loginFields.length > 0) {
193
                for (var i = 0; i < loginFields.length; i++) {
194
                    var form = getFormFromElement(loginFields[i][0]);
195
                    if (!disablePasswordPicker) {
196
                        createPasswordPicker(loginFields[i], form);
0 ignored issues
show
Bug introduced by
The call to createPasswordPicker seems to have too many arguments starting with form.
Loading history...
197
                    }
198
199
                    if (settings.disable_browser_autofill) {
200
                        $j(form).attr('autocomplete', 'off');
201
                    }
202
203
                    //Password miner
204
                    /* jshint ignore:start */
205
                    if (!settings.hasOwnProperty('ignored_sites') || settings.ignored_sites.findUrl(url) !== -1) {
206
                        $j(form).submit((function (loginFields) {
207
                            return function () {
208
                                formSubmitted(loginFields);
209
                            };
210
                        })(loginFields[i]));
211
                    }
212
                    /* jshint ignore:end */
213
                }
214
215
                API.runtime.sendMessage(API.runtime.id, {
216
                    method: "getCredentialsByUrl",
217
                    args: url
218
                }).then(function (logins) {
219
                    console.log('Found ' + logins.length + ' logins for this site');
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
220
                    if (logins.length === 1) {
221
                        API.runtime.sendMessage(API.runtime.id, {method: 'isAutoFillEnabled'}).then(function (isEnabled) {
222
                            if (isEnabled) {
223
                                enterLoginDetails(logins[0]);
224
                            }
225
                        });
226
                    }
227
228
                });
229
            }
230
231
        });
232
    }
233
234
    function minedLoginSaved(args) {
235
        // If the login added by the user then this is true
236
        if (args.selfAdded) {
237
            enterLoginDetails(args.credential);
238
        }
239
    }
240
241
    _this.minedLoginSaved = minedLoginSaved;
242
243
    function copyText(text) {
244
        var txtToCopy = document.createElement('input');
245
        txtToCopy.style.left = '-300px';
246
        txtToCopy.style.position = 'absolute';
247
        txtToCopy.value = text;
248
        document.body.appendChild(txtToCopy);
249
        txtToCopy.select();
250
        document.execCommand('copy');
251
        txtToCopy.parentNode.removeChild(txtToCopy);
252
    }
253
254
    _this.copyText = copyText;
255
256
    function init() {
257
        checkForMined();
258
        initForms();
259
    }
260
261
    var readyStateCheckInterval = setInterval(function () {
262
        if (document.readyState === "complete") {
263
            clearInterval(readyStateCheckInterval);
264
            API.runtime.sendMessage(API.runtime.id, {method: 'getMasterPasswordSet'}).then(function (result) {
265
                if (result) {
266
                    init();
267
                    var body = document.getElementsByTagName('body')[0];
0 ignored issues
show
Unused Code introduced by
The variable body seems to be never used. Consider removing it.
Loading history...
268
                    // observeDOM(body, function () {
269
                    //     initForms();
270
                    // });
271
                } else {
272
                    console.log('[Passman extension] Stopping, vault key not set');
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
273
                }
274
            });
275
        }
276
    }, 10);
277
278
    API.runtime.onMessage.addListener(function (msg, sender) {
279
        //console.log('Method call', msg.method);
280
        if (_this[msg.method]) {
281
            _this[msg.method](msg.args, sender);
282
        }
283
    });
284
});
285